package p.ithorns.framework.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * TypeConverter
 * 目标类型转换器
 *
 * @author HtL
 * @date 2024/11/25 13:38
 * @since 1.0.0
 */
public class TypeConverter {

    private final static Logger log = LoggerFactory.getLogger(TypeConverter.class);

    private static final Map<Class<?>, Function<Object, Object>> CONVERTERS = new ConcurrentHashMap<>(16);

    private static final Set<Class<?>> PRIMITIVE_BOX_CLASSES = Set.of(
            Boolean.class, Character.class, Byte.class, Short.class,
            Integer.class, Long.class, Float.class, Double.class
    );


    static {
        // 注册各种类型的转换器
        registerConverter(String.class, Object::toString);

        registerConverter(Integer.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                try {
                    return Integer.parseInt(str);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to Integer", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Integer");
            }
        });

        registerConverter(int.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return 0;
                }
                try {
                    return Integer.parseInt(str);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to int", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to int");
            }
        });

        registerConverter(Long.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).longValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                try {
                    // 去掉字符串中的 'L' 或 'l' 后缀
                    String cleanedValue = str.replaceAll("[Ll]$", "");
                    return Long.parseLong(cleanedValue);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to Long", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Long");
            }
        });

        registerConverter(long.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).longValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return 0L;
                }
                try {
                    // 去掉字符串中的 'L' 或 'l' 后缀
                    String cleanedValue = str.replaceAll("[Ll]$", "");
                    return Long.parseLong(cleanedValue);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to long", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to long");
            }
        });

        registerConverter(Double.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                try {
                    // 去掉字符串中的 'D' 或 'd' 后缀
                    String cleanedValue = str.replaceAll("[Dd]$", "");
                    return Double.parseDouble(cleanedValue);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to Double", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Double");
            }
        });

        registerConverter(double.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return 0D;
                }
                try {
                    // 去掉字符串中的 'D' 或 'd' 后缀
                    String cleanedValue = str.replaceAll("[Dd]$", "");
                    return Double.parseDouble(cleanedValue);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to double", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to double");
            }
        });

        registerConverter(Float.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).floatValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                try {
                    // 去掉字符串中的 'F' 或 'f' 后缀
                    String cleanedValue = str.replaceAll("[Ff]$", "");
                    return Float.parseFloat(cleanedValue);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to Float", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Float");
            }
        });

        registerConverter(float.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).floatValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return 0F;
                }
                try {
                    // 去掉字符串中的 'F' 或 'f' 后缀
                    String cleanedValue = (str).replaceAll("[Ff]$", "");
                    return Float.parseFloat(cleanedValue);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to float", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to float");
            }
        });

        registerConverter(Boolean.class, value -> {
            if (value instanceof Boolean) {
                return value;
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return false;
                }
                return Boolean.valueOf(str);
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Boolean");
            }
        });

        registerConverter(boolean.class, value -> {
            if (value instanceof Boolean) {
                return value;
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return false;
                }
                return Boolean.parseBoolean(str);
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to boolean");
            }
        });

        registerConverter(Character.class, value -> {
            if (value instanceof Character) {
                return value;
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                return str.charAt(0);
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Character");
            }
        });

        registerConverter(char.class, value -> {
            if (value instanceof Character) {
                return value;
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return (char) 0;
                }
                return str.charAt(0);
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to char");
            }
        });

        registerConverter(Byte.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).byteValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                try {
                    return Byte.parseByte(str);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to Byte", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Byte");
            }
        });

        registerConverter(byte.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).byteValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return 0;
                }
                try {
                    return Byte.parseByte(str);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to byte", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to byte");
            }
        });

        registerConverter(Short.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).shortValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return null;
                }
                try {
                    return Short.parseShort(str);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to Short", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to Short");
            }
        });

        registerConverter(short.class, value -> {
            if (value instanceof Number) {
                return ((Number) value).shortValue();
            } else if (value instanceof String str) {
                if (isNullStr(str)) {
                    return 0;
                }
                try {
                    return Short.parseShort(str);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse " + value + " to short", e);
                }
            } else {
                throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to short");
            }
        });
    }

    public static void registerConverter(Class<?> type, Function<Object, Object> converter) {
        CONVERTERS.put(type, converter);
    }

    public static boolean isNullStr(String str) {
        return null == str || str.length() == 0 || "null".equals(str);
    }

    public static <T> T convert(Object value, Class<T> targetType) {
        if (value == null) {
            return null;
        }

        if (targetType.isInstance(value)) {
            return (T) value;
        }

        Function<Object, Object> converter = CONVERTERS.get(targetType);
        if (converter != null) {
            try {
                return (T) converter.apply(value);
            } catch (Exception e) {
                throw new IllegalArgumentException("Failed to convert " + value.getClass() + " to " + targetType, e);
            }
        }

        throw new IllegalArgumentException("Unsupported conversion from " + value.getClass() + " to " + targetType);
    }

    public static boolean isPrimitiveOrString(Class<?> clazz) {
        // 判断clazz是否是基本数据类型或基本类型的包装类 ，以及String类型
        return clazz.isPrimitive() || PRIMITIVE_BOX_CLASSES.contains(clazz) ||  clazz.equals(String.class);
    }


    public static void main(String[] args) {
//        System.out.println(TypeConverter.convert("123", Integer.class)); // 输出: 123
//        System.out.println(TypeConverter.convert(456L, int.class));      // 输出: 456
//        System.out.println(TypeConverter.convert("789", Long.class));    // 输出: 789
//        System.out.println(TypeConverter.convert(10.5, Double.class));   // 输出: 10.5
//        System.out.println(TypeConverter.convert("true", Boolean.class));// 输出: true
//        System.out.println(TypeConverter.convert("A", Character.class)); // 输出: A
//        System.out.println(TypeConverter.convert("100", byte.class));    // 输出: 100
//        System.out.println(TypeConverter.convert("32767", short.class)); // 输出: 32767

        int convert = TypeConverter.convert("null", int.class);
        System.out.println(convert);

        byte l1 = TypeConverter.convert(456L, byte.class);
        System.out.println(l1);
    }

}